package com.eptok.gw.szcups.socket.server;

import java.net.InetSocketAddress;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.executor.ExecutorFilter;
import org.apache.mina.transport.socket.SocketSessionConfig;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;

/**
 * @author:heqishan, Email:heqishan@gmail.com 2013-3-5 下午02:32:45
 */
public class AsynServer {

	private NioSocketAcceptor acceptor;
	private InetSocketAddress addr;
	private ExecutorService pool;

	private ServerConfig serverConfig;

	public AsynServer(ServerConfig serverConfig) {
		this.serverConfig = serverConfig;
	}

	public void startListen() throws Exception {
		addr = new InetSocketAddress(serverConfig.getHost(), serverConfig
				.getPort());

		acceptor = new NioSocketAcceptor();
		acceptor.setBacklog(100);
		acceptor.setReuseAddress(false);
		pool = Executors.newCachedThreadPool();
		acceptor.getFilterChain().addFirst("codec",
				new ProtocolCodecFilter(serverConfig.getCodecFactory()));
		acceptor.getFilterChain().addLast("threadPool",
				new ExecutorFilter(pool));
		acceptor.setHandler(serverConfig.getIoHandlerAdapter());

		SocketSessionConfig config = acceptor.getSessionConfig();
		config.setReceiveBufferSize(2048 * 100);
		config.setMaxReadBufferSize(2048 * 100);
		config.setMinReadBufferSize(2048 * 25);
		config.setSendBufferSize(2048 * 10);
		if (config.getSoLinger() > 0) {
			config.setSoLinger(-1);
		}
		config.setIdleTime(IdleStatus.BOTH_IDLE, 120);

		acceptor.bind(addr);
	}

	public void stopListen() {
		acceptor.unbind(addr);
		acceptor.dispose();
		if (pool != null && !pool.isShutdown()) {
			try {
				if (!pool.awaitTermination(2, TimeUnit.SECONDS)) {
					pool.shutdownNow();
				}
			} catch (final InterruptedException ie) {
				pool.shutdownNow();
			}
		}
	}
}
